package com.dong6662.spring.web.server;

import com.dong6662.spring.web.servlet.DispatcherServlet;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;

// TODO: 2021/5/14 这段代码目前不是核心部分，后面找时间来研究一下
public class TomcatServer {
    private Tomcat tomcat;
    private String[] args;

    public TomcatServer(String[] args){
        this.args = args;
    }

    public void startServer() throws LifecycleException {
        tomcat = new Tomcat();
        tomcat.setPort(8088);
        // TODO: 2021/5/14 这个start()看源码应该是开启tomcat服务器的意思
        tomcat.start();

        // TODO: 2021/5/14 接下来应该是创建两个最重要的对象：Context和Servlet。Servlet好理解，
        //  但是Context有点抽象 ，感觉Context就是一个webapp呢？只是猜测

        // new 一个标准的 context 容器并设置访问路径；
        // 同时为 context 设置生命周期监听器。
        Context context = new StandardContext();
        context.setPath("");
        context.addLifecycleListener(new Tomcat.FixContextListener());


        // 新建一个 DispatcherServlet 对象，这个是我们自己写的 Servlet 接口的实现类，
        // 然后使用 `Tomcat.addServlet()` 方法为 context 设置指定名字的 Servlet 对象，
        // 并设置为支持异步。
        DispatcherServlet servlet = new DispatcherServlet();
        // TODO: 2021/5/14 疑问：很可惜tomcat一系列的jar包都没有javaDoc，只能靠看代码并且猜测。好像实例的addServlet最终都是会调用静态的addServlet的
        Tomcat.addServlet(context, "dispatcherServlet", servlet)
                .setAsyncSupported(true);

        // Tomcat 所有的线程都是守护线程，
        // 如果某一时刻所有的线程都是守护线程，那 JVM 会退出，
        // 因此，需要为 tomcat 新建一个非守护线程来保持存活，
        // 避免服务到这就 shutdown 了
        context.addServletMappingDecoded("/", "dispatcherServlet");

        tomcat.getHost().addChild(context);

        Thread tomcatAwaitThread = new Thread("tomcat_await_thread") {
            @Override
            public void run() {
                //这个Thread可以看作是内部内，TomcatServer.this表明调用该内部内的外层类：TomcatServer，的实例。
                // 这种用法挺常见的，基本在内部内访问想要外层类实例的时候
                //https://zhidao.baidu.com/question/229291731.html 说的很透彻
                TomcatServer.this.tomcat.getServer().await();
            }
        };
        //不将该线程设置为守护线程
        tomcatAwaitThread.setDaemon(false);
        tomcatAwaitThread.start();

    }
}
